问题的由来
JavaScript代码:
//JavaScript
console.log(0.3 - 0.2 == 0.2 - 0.1) //false
Python代码:
#!/usr/bin/env python
# -*- coding:utf8 -*-
print 0.3 - 0.2 == 0.2 - 0.1 #False
同样的原因:浮点数在数字计算机中表示不精确的问题。
JavaScript代码:
//JavaScript
console.log(0.3 - 0.2) //0.09999999999999998
console.log(0.2 - 0.1) //0.1
Python代码:
#!/usr/bin/env python
# -*- coding:utf8 -*-
print 0.3 - 0.2 #0.09999999999999998
print 0.2 - 0.1 #0.1
都知道在数字计算机中用二进制位来表示数据,数字当然也不例外。
1 定点表示法
二进制小数的表示方式为:
bmbm-1…b3b2b1.b1b2b3…b-n+1b-n
上式表示的数值为
b = sum(bi * 2i),其中-n <= i <= m
这样就能很自然的表示我们的小数,这种小数点固定的表示方法叫做定点表示法(见名知意哦!)
然而,我们很快看出他的问题了,假设计算机字长为64位,我们要表示一个264的数字就已经把数位占完了,再大一丁点的数就没法表示了,比如说再大0.1,总得要一位表示小数吧?搞不定~~
于是就有了下面的表示方法,有定点,自然就会有不定点,这种小数点不固定的方法(望文生义哦!)叫做浮点表示法(小数点浮动,^_^),这是计算机中普遍使用的表示方法。
2 浮点表示法
浮点表示法就数位分为符号(sign)、指数(exponent)、有效位数(significant)(尾数)三部分:
32位浮点数(单精度浮点数)表示:1位符号位,8位指数,23位尾数
31———————————-0
+-+——–+———————–+
64位浮点数(双精度浮点数)表示:1位符号位,11位指数,52位尾数,能进一步提高精度。
63—————————————————————–0
+-+———–+—————————————————-+
于是对于一个数b = (-1)s * M * 2E
综上可以看出浮点数的表示本身就不是精确值,精确的是2-i的和
所以
0.3 = 2-2+2-5+2-6+2-9…..
0.2 = 2-3+2-4+2-7+2-8…..
0.1 = 2-4+2-6+2-7+2-8…..
省略号表示凑够尾数的有效位数为止。
由此可以看出,确实是很难用等于来判断浮点数的取值。
解决办法:
A-B <= 误差范围,差不多就行了
比如说:
(0.3-0.2) - (0.2-0.1) <= 0.0000000001
或者
(0.3-0.2) - (0.2-0.1) <= 1.0e-10
未完待续。。。
最后更新: 2022年03月02日 03:32
原始链接: http://rawbin-.github.io/dev-general/2015-03-31-ieee-745/